package ch.unifr.dokpe.htmlpicker;

import java.util.*;

/**
 * Manages a list of maps. Each map holds application data (url, parameters, ...) 
 * each stored with predefinned keys, and the text segments extracted from the page (stored with their corresponding labels as key),
 * for an occurence of the labels on the page.
 * <p>A new map is added to the list for each occurence of the labels, and the application data are duplicated in the map
 * <p>The keys for retrieving application data are<ul>
 * <li>_u retrieves the url of the page</li>
 * <li>_0, _1, _2 retrives the parameters read in the file at param.col 1, 2, 3 ...</li>
 * <li>_l retrieves the a line from the parameter file not used in the url
 * (depends on the properties param.file.skipLine and param.file.columns)</li>
 * </ul>
 */


public class MapProvider {

  /*List that stores the url, parameters, and text extracted from a page for a group of labels*/
   private List<Map<String,String>> lData = new ArrayList<Map<String,String>>();
   private ListIterator<Map<String,String>> iterator =null;
   public static byte DEBUG=(byte)0; 
   private Map <String,String> currentMap = null;
   private Map<String,String> templateMap = null;

   private int labelscount;

   /*List that stores duplpicated application data and text extracted for the next (ie &lt;1) occurence of the labels */
   private List <Map<String,String>> lDataBis = null;
   
   /* a map of the labels to search, and their number of occurence in a single html page*/
   private Map<String, Integer> labels;

   public MapProvider(){
 	newMap();
   }

  /**
   * @return Map the last map added on the list or null
   */
   public Map<String,String> getmap(){
	   int last = lData.size();
	   if (last > 0) {
	   	return lData.get(last - 1);
	   } else  {return null;}
	   }
 /**
  * Calls for each new builded url
  * add a new empty map in the list 
  */
   public void newMap(){
       Map <String,String> map  = new HashMap<String,String>();
   	lData.add(map);
	//iterator.add(map);
   }

  /**
   * Add a map at index p 
   * @param p the position where to add the map
   * @param map the map to add
   */
   public Map<String,String> add(int p, Map<String, String> map){
	   lData.add(p, map);
	   //iterator.add(map);
	   return map;

    }
    /**
     * Call this method before traversing the list with next
     * @return ListIterator a new listIterator for the list
     */

   public ListIterator <Map<String,String>> getNewIterator(){
	    iterator = lData.listIterator();
	   return iterator;
   }

   /**
    * @return a existing ListIterator for the list or null 
    * if {@link #getNewIterator getNewIterator} has been called
    */
   public ListIterator  <Map<String,String>> getIterator(){return iterator;}


  /**
   * @return the number of maps in the list
   */
   public int size(){return lData.size();}
   
   /**
    * @return the list of maps
    */
   public List<Map<String,String>> getlist(){return lData;}
   
   /**
    * clear the list
    */
   public void clear(){ lData.clear();}
    
   /**
    * Calls when a new page has been loaded. 
    * Fills a template map with the content of the map returned, create a second list of maps. 
    * to store duplicate labels on a page.
    * Remembers the returned map in currentMap.
    * @return the next map in the list 
    *  {@link #getNewIterator getNewIterator} has been called
    */
   public Map <String,String> next(){
	   Map <String, String> result = null;
	   if (iterator.hasNext()){
		   if (DEBUG>=3) {System.out.println("MapProvider.next: returning a map");}
		   	//next is called at each new page load therefore we get a empty labels Map
	         	labels = new  HashMap<String, Integer>();
	  		lDataBis = new ArrayList<Map<String,String>>();
			templateMap = new HashMap<String,String>();
			result = iterator.next();
			templateMap.putAll(result);
			currentMap = result;
		
	   } else {if (DEBUG>=3) {System.out.println("MapProvider.next: all " +  + lData.size() +" maps returned from list");}}
	   return result;

   }

    /**
     * @return the map that was given with the last call to {@link #next next}
     */
    //public Map <String, String> current(){return currentMap;}

    /**
     * @return a copy of the holding the content of map received with the last call to {@link #next next}
     */
    public Map <String, String> getTemplate(){return templateMap;}

    /**
     * Initialize to 0 the count of the labels on a page
     * @param s set of labels 
     */
    public void setLabels( Set<String> s){
	for (String label : s){
		if (DEBUG>=3) System.out.println("setLabels: " + label);
		labels.put(label, new Integer(0));
	}
	labelscount = 0;
    }

 /**
  * Add a map the to a second list of maps lDataBis.
 * For the first occurence of the labels, the current map is added. 
 * For the next occurences at the first label, a new map filled with the values from templateMap is added.
 * For the next occurences of the others labels return the corresponding map from lDataBis
 * labels.get(label) gives how many times label has been search on a page
 * @param label the label searched on a page
 * @return the current map if label occures for the first time on the page else return a new map copied from templateMap
 */
public Map<String,String> getCurrentMap(String label){
	if (DEBUG>=3) System.out.println("getCurrentMap: listMap.size : " + lDataBis.size());
	//pos gives howmany times we have seen a label in the same page
	int pos = labels.get(label).intValue();
	labels.put(label, new Integer(pos+1));

	if (lDataBis.size() == 0) {

			if (DEBUG>=3) System.out.println("getCurrentMap: return currentmap and add it to list of duplicates at pos " + pos);
			lDataBis.add(pos, currentMap);
			return currentMap;
	

	} else if (lDataBis.size() > pos) { //we have added more maps in the list 
			                     //then the occurence of the current label: return (a ref to) the map at 
					     //corresponding position  (= occurence of the current label)
			//if (DEBUG>=3) System.out.println("getCurrentMap: return an existing map from list of duplicates at pos " + (lDataBis.size() - 1 - pos));
			if (DEBUG>=3) System.out.println("getCurrentMap: return an existing map from list of duplicates at pos " + pos);
			return lDataBis.get(pos);
			//return currentMap;
	} else { //the last map in the list is at lDataBis.size-1 and the current label has been found more then that
			//create an empty map give it the content of templateMap
			//add the map to the list of duplicates and to the iterator
			if (DEBUG>=3) { System.out.println("getCurrentMap: add new map to the list of duplicates at pos " + pos);
					System.out.println("               add the map to the main list and return the map");
			}
			Map<String,String> newMap = new HashMap<String,String>();
			newMap.putAll(templateMap);
			lDataBis.add(pos, newMap);
			iterator.add(newMap);
			return newMap;
			//return currentMap;
	}
	
 }//getCurrentMap

} //class

//@MITLI@
